import datetime
import logging

from sqlalchemy import func

from base.connection import get_db_session
from common.definition import CashMethod, PayType, ret_msg
from conf import config
from helper.mp_helper import send_text_message
from helper.payment.balance import BalanceHandler
from helper.payment.pay_util import generator_trade_no
from helper.payment.wechat_pay import WechatPay
from util.math_util import convert2decimal

logger = logging.getLogger("helper")


class CashApplyHelper(object):
    @staticmethod
    def deal_cash_bank_card(open_id, agency_uid, fee):
        # 检查是否填写了银行卡等信息
        class Benefit(object):
            pass

        class CashApply(object):
            pass

        class AgencyIncomeSetup(object):
            pass

        session = get_db_session([
            {"db_table": "slbt_agency_income_setup", "model": AgencyIncomeSetup},
            {"db_table": "sdet_benefit", "model": Benefit},
            {"db_table": "slbt_cash_apply", "model": CashApply},
        ])
        total_fee = session.query(func.sum(Benefit.fee)).filter_by(agency_uid=agency_uid, status=1,
                                                                   is_valid=1, is_finish=1).scalar()
        total_fee = convert2decimal(total_fee)

        # 已提现金额
        query = session.query(func.sum(CashApply.slbf_ca_fee))
        # 审核中的也计入已提现，避免重复提交审核
        cashed_fee = query.filter_by(slbf_ca_agency_uid=agency_uid, slbf_ca_factory_uid=config.FACTORY_UID).filter(
            CashApply.slbf_ca_status != -1).scalar()
        cashed_fee = convert2decimal(cashed_fee)
        enable_fee = total_fee - cashed_fee
        logger.info("提现：open_id=%s,total_fee=%s,cashed_fee=%s,enable_fee=%s,fee=%s" % (
            open_id, total_fee, cashed_fee, enable_fee, fee))
        # 检查提现金额是否大于可提现金额
        if fee > enable_fee:
            logger.error(f"申请银行卡提现: 申请的金额大于可提现金额 agency_uid={agency_uid}")
            return ret_msg(-1, error_message="申请的金额大于可提现金额")

        income_setup = session.query(AgencyIncomeSetup).filter_by(slbf_ais_agency_uid=agency_uid).first()
        if not income_setup or not income_setup.slbf_ais_card_no:
            logger.error(f"申请银行卡提现: 未设置收款银行卡 agency_uid={agency_uid}")
            return ret_msg(-1, error_message="未设置收款银行卡")

        # 添加待审核提现记录，等待后台审核
        now = datetime.datetime.now()
        ca = CashApply()
        ca.slbf_ca_apply_fee = fee
        ca.slbf_ca_apply_account = open_id
        ca.slbf_ca_factory_uid = config.FACTORY_UID
        ca.slbf_ca_agency_uid = agency_uid
        ca.slbf_ca_fee = fee
        ca.slbf_ca_real_total_fee = fee
        ca.slbf_ca_total_fee = total_fee
        ca.slbf_ca_verify_time = now
        ca.slbf_ca_rate = income_setup.slbf_ais_wechat_rate
        ca.slbf_ca_type = PayType.WECHAT
        ca.slbf_ca_status = 0
        ca.slbf_ca_create_time = now
        ca.slbf_ca_method = CashMethod.BANK_CARD
        session.add(ca)
        session.commit()
        logger.info("申请银行卡提现: slbf_ca_id=%s" % ca.slbf_ca_id)
        return ret_msg()

    @staticmethod
    def deal_cash_wechat(open_id, agency_uid, fee, name):
        class Benefit(object):
            pass

        class CashApply(object):
            pass

        class AgencyIncomeSetup(object):
            pass

        session = get_db_session([
            {"db_table": "slbt_agency_income_setup", "model": AgencyIncomeSetup},
            {"db_table": "sdet_benefit", "model": Benefit},
            {"db_table": "slbt_cash_apply", "model": CashApply},
        ])

        # 合伙人提现
        total_fee = session.query(func.sum(Benefit.fee)).filter_by(agency_uid=agency_uid, status=1,
                                                                   is_valid=1, is_finish=1).scalar()
        total_fee = convert2decimal(total_fee)

        # 已提现金额
        query = session.query(func.sum(CashApply.slbf_ca_fee))
        # 审核中的也计入已提现，避免重复提交审核
        cashed_fee = query.filter_by(slbf_ca_agency_uid=agency_uid, slbf_ca_factory_uid=config.FACTORY_UID).filter(
            CashApply.slbf_ca_status != -1).scalar()
        cashed_fee = convert2decimal(cashed_fee)
        enable_fee = total_fee - cashed_fee
        logger.info("提现：合伙人提现 open_id=%s,total_fee=%s,cashed_fee=%s,enable_fee=%s,fee=%s" % (
            open_id, total_fee, cashed_fee, enable_fee, fee))

        # 检查提现金额是否大于可提现金额
        if fee > enable_fee:
            logger.error(f"申请微信提现: 申请的金额大于可提现金额 agency_uid={agency_uid}")
            send_text_message(open_id, "亲，微信提现失败: 申请的金额大于可提现金额。如有问题，请联系客服 18926405852(微信同号)")
            return ret_msg(-1, error_message="申请的金额大于可提现金额")

        # 添加待审核提现记录，等待后台审核
        now = datetime.datetime.now()
        ca = CashApply()
        ca.slbf_ca_apply_fee = fee
        ca.slbf_ca_apply_account = open_id
        ca.slbf_ca_factory_uid = config.FACTORY_UID
        ca.slbf_ca_agency_uid = agency_uid
        ca.slbf_ca_fee = fee
        ca.slbf_ca_real_total_fee = fee
        ca.slbf_ca_total_fee = total_fee
        ca.slbf_ca_verify_time = now
        ca.slbf_ca_rate = 1
        ca.slbf_ca_type = PayType.WECHAT
        ca.slbf_ca_status = 0
        ca.slbf_ca_create_time = now
        ca.slbf_ca_method = CashMethod.WECHAT
        session.add(ca)
        session.commit()
        logger.info("申请微信提现: slbf_ca_id=%s" % ca.slbf_ca_id)
        if config.CASH_WECHAT_IS_NEED_CHECK:
            logger.debug("微信提现需要审核")
            return ret_msg()

        # 调企业付款接口,如果付款成功的话，将状态改成已审核
        trade_no = ca.slbf_ca_id
        inc_pay_ret = WechatPay.inc_pay(open_id, name, trade_no, fee, desc="收益提现:uid=%s" % agency_uid)
        if inc_pay_ret:
            cash_apply = session.query(CashApply).filter_by(slbf_ca_id=trade_no).one()
            cash_apply.slbf_ca_status = 1
            wechat_trade_no = inc_pay_ret.get("payment_no")
            if not wechat_trade_no:
                wechat_trade_no = inc_pay_ret.get("detail_id")
            cash_apply.slbf_ca_info = wechat_trade_no
            cash_apply.slbf_ca_message = "微信提现"
            session.commit()
            logger.info("微信提现成功：open_id=%s,fee=%s,wechat_trade_no=%s" % (open_id, fee, wechat_trade_no))
            return ret_msg()

        logger.error("微信提现失败：open_id=%s,fee=%s,trade_no=%s" % (open_id, fee, trade_no))
        send_text_message(open_id, "亲，微信提现失败，请检查提现银行卡实名和微信认证实名是否一致。修改银行卡实名方法：在提现页添加/修改绑定银行卡信息。客服电话 18926405852(微信同号)")
        return ret_msg(-1, error_message=f"微信提现失败，提现编号为{trade_no}。请检查银行卡实名信息和微信实名是否一致。请联系客服 18926405852(微信同号)")

    @staticmethod
    def deal_cash_balance(open_id, agency_uid, fee, ip):
        class Benefit(object):
            pass

        class CashApply(object):
            pass

        class AgencyIncomeSetup(object):
            pass

        session = get_db_session([
            {"db_table": "slbt_agency_income_setup", "model": AgencyIncomeSetup},
            {"db_table": "sdet_benefit", "model": Benefit},
            {"db_table": "slbt_cash_apply", "model": CashApply},
        ])
        total_fee = session.query(func.sum(Benefit.fee)).filter_by(agency_uid=agency_uid, status=1,
                                                                   is_valid=1, is_finish=1).scalar()
        total_fee = convert2decimal(total_fee)

        # 已提现金额
        query = session.query(func.sum(CashApply.slbf_ca_fee))
        # 审核中的也计入已提现，避免重复提交审核
        cashed_fee = query.filter_by(slbf_ca_agency_uid=agency_uid, slbf_ca_factory_uid=config.FACTORY_UID).filter(
            CashApply.slbf_ca_status != -1).scalar()
        cashed_fee = convert2decimal(cashed_fee)
        enable_fee = total_fee - cashed_fee
        logger.info("申请提现到余额：open_id=%s,total_fee=%s,cashed_fee=%s,enable_fee=%s,fee=%s" % (
            open_id, total_fee, cashed_fee, enable_fee, fee))
        # 检查提现金额是否大于可提现金额
        if fee > enable_fee:
            logger.error(f"申请提现到余额: 申请的金额大于可提现金额 agency_uid={agency_uid}")
            return ret_msg(-1, error_message="申请的金额大于可提现金额")

        # 添加充值记录
        is_ok = BalanceHandler.add_manual_money(open_id, fee, pay_content="提现到余额", operator=open_id, ip=ip)
        if not is_ok:
            logger.error(f"提现到余额失败 agency_uid={agency_uid}")
            return ret_msg(-1, error_message="提现到余额失败")

        # 添加提现记录
        now = datetime.datetime.now()
        ca = CashApply()
        ca.slbf_ca_apply_fee = fee
        ca.slbf_ca_apply_account = open_id
        ca.slbf_ca_factory_uid = config.FACTORY_UID
        ca.slbf_ca_agency_uid = agency_uid
        ca.slbf_ca_fee = fee
        ca.slbf_ca_real_total_fee = fee
        ca.slbf_ca_total_fee = total_fee
        ca.slbf_ca_verify_time = now
        ca.slbf_ca_rate = 1
        ca.slbf_ca_type = PayType.WECHAT
        ca.slbf_ca_status = 1
        ca.slbf_ca_create_time = now
        ca.slbf_ca_method = CashMethod.BALANCE
        session.add(ca)
        session.commit()
        logger.info("slbf_ca_id=%s" % ca.slbf_ca_id)
        return ret_msg()

    @staticmethod
    def deal_user_cash_wechat(open_id, fee, name):
        """
        普通用户可提现余额提现

        :param open_id:
        :param fee:
        :param name:
        :return:
        """

        class AccountMoney(object):
            pass

        session = get_db_session([
            {"db_table": "ebt_account_money", "model": AccountMoney},
        ])

        # 普通用户余额提现
        account_money = session.query(AccountMoney).filter_by(ebf_am_user_id=open_id).first()
        enable_fee = convert2decimal(account_money.ebf_am_cash)

        logger.info(f"提现：普通用户余额提现 open_id={open_id}, cashable_fee={enable_fee},fee={fee}")

        # 检查提现金额是否大于可提现金额
        if fee > enable_fee:
            logger.error(f"申请微信提现: 申请的金额大于可提现金额 open_id={open_id}, cashable_fee={enable_fee}, fee={fee}")
            return ret_msg(-1, error_message="申请的金额大于可提现金额")

        # 处理可提现余额
        trade_no = generator_trade_no()

        ok = BalanceHandler.add_account_cash(open_id, -fee, trade_no, pay_content="微信提现扣减余额")
        if not ok:
            logger.error(f"申请微信提现: 可提现余额扣减出错 open_id={open_id} fee={fee} trade_no={trade_no}")
            return ret_msg(-1, error_message="可提现余额处理出错")

        # 调企业付款接口
        inc_pay_ret = WechatPay.inc_pay(open_id, name, trade_no, fee, desc=f"余额提现: oid={open_id}")
        if inc_pay_ret:
            wechat_trade_no = inc_pay_ret.get("payment_no")
            if not wechat_trade_no:
                wechat_trade_no = inc_pay_ret.get("detail_id")
            logger.info("微信提现成功：open_id=%s,fee=%s,wechat_trade_no=%s" % (open_id, fee, wechat_trade_no))
            return ret_msg()

        # 微信提现失败，给可提现账户充值
        logger.error("微信提现失败：open_id=%s,fee=%s,trade_no=%s" % (open_id, fee, trade_no))
        ok = BalanceHandler.add_account_cash(open_id, fee, trade_no, pay_content="微信提现失败返还余额")
        if not ok:
            logger.error(f"微信提现失败，提现金额返还充值失败 open_id={open_id} fee={fee} trade_no={trade_no}")
        return ret_msg(-1, error_message="微信提现失败，请联系管理员，提现编号为%s" % trade_no)
